package ae.pcfc.cldos.online.common.facade.provider;

import java.util.HashMap;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.cldos.online.common.ConstantsCommon.Steps;
import ae.pcfc.cldos.online.common.ConstantsCommon;
import ae.pcfc.cldos.online.common.UltimusConstants;
import ae.pcfc.cldos.online.common.UltimusConstants.AdminDecision;
import ae.pcfc.cldos.online.common.UltimusConstants.ApplicationResubmitDecision;
import ae.pcfc.cldos.online.common.UltimusConstants.EmployeeType;
import ae.pcfc.cldos.online.common.clddb.domain.AppMetaData;
import ae.pcfc.cldos.online.common.clddb.domain.ApplicationStatus;
import ae.pcfc.cldos.online.common.clddb.domain.Process;
import ae.pcfc.cldos.online.common.clddb.domain.ReviewComments;
import ae.pcfc.cldos.online.common.clddb.domain.ServiceMaster;
import ae.pcfc.cldos.online.common.clddb.domain.TaskMaster;
import ae.pcfc.cldos.online.common.clddb.domain.manager.AppMetaDataDOM;
import ae.pcfc.cldos.online.common.clddb.domain.manager.ReviewCommentsDOM;
import ae.pcfc.cldos.online.common.clddb.domain.manager.provider.AppMetaDataDOMImpl;
import ae.pcfc.cldos.online.common.etksdb.domain.Client;
import ae.pcfc.cldos.online.common.etksdb.domain.User;
import ae.pcfc.cldos.online.common.etksdb.domain.manager.UserDomainObjectManager;
import ae.pcfc.cldos.online.common.exception.BadAppException;
import ae.pcfc.cldos.online.common.exception.InvalidEmpIdException;
import ae.pcfc.cldos.online.common.exception.UltimusAppException;
import ae.pcfc.cldos.online.common.facade.BaseProcesesFacade;
import ae.pcfc.cldos.online.common.facade.CompanyAdminFacade;
import ae.pcfc.cldos.online.common.manager.BuisnessValidationManager;
import ae.pcfc.cldos.online.common.manager.DataTransferManager;
import ae.pcfc.cldos.online.common.manager.FNPManager;
import ae.pcfc.cldos.online.common.manager.GSEmployeeDetailsManager;
import ae.pcfc.cldos.online.common.manager.GsInfoManager;
import ae.pcfc.cldos.online.common.manager.TaskAndNotificationsManager;
import ae.pcfc.cldos.online.common.tscdb.domain.TTscClientCompany;
import ae.pcfc.cldos.online.common.vo.AdminDecisionVO;
import ae.pcfc.cldos.online.common.vo.AppSaveResponseVO;
import ae.pcfc.cldos.online.common.vo.TransferDataVO;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.common.vo.fnp.FNPPaymentAdviceVO;
import ae.pcfc.cldos.online.fnp.ConstantsFNP;
import ae.pcfc.cldos.online.gs.ConstantsGS;
import ae.pcfc.cldos.online.gs.service.client.vo.GSFinancialDataVO;
import ae.pcfc.cldos.online.gs.service.client.vo.NotificationVO;
import ae.pcfc.cldos.online.net.service.vo.NOCDetailsFromGSVO;
import ae.pcfc.cldos.online.wf.ConstantsWF;
import ae.pcfc.cldos.online.wf.service.client.GenericVisaWF;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.EmploymentVisaAppInfoVO;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.EmploymentVisaCancelationAppInfoVO;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.EmploymentVisaRenewAppInfo;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.NocLetterAppInfoVO;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.VisitVisaAppInfoVO;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.VisitVisaCancelAppInfo;
import ae.pcfc.cldos.online.wf.service.client.vo.base.BaseSubmitGVariablesVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.CompleteStepVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.LaunchIncedentVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.EVRenewalSubmGVarVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.MainUserActionGVarVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.TerminateEVSubmGVarVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.VisaResubmitGVarVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.VisaSubmitGVarVO;

/**
 * 
 * @author arosa
 *
 */
public class CompanyAdminFacadeImpl extends BaseProcesesFacade implements CompanyAdminFacade {

	private AppMetaDataDOM appMetaDataDOM;
	private ae.pcfc.cldos.online.common.etksdb.domain.manager.ClientDOM clientDOM;
	private ae.pcfc.cldos.online.common.tscdb.domain.manager.TTscClientCompanyDOM tTscClientCompanyDOM;
	private GsInfoManager gsInfoManager;
	private BuisnessValidationManager buisnessValidationManager;
	private ReviewCommentsDOM reviewCommentsDOM;
	private DataTransferManager dataTransferManager;
	private GSEmployeeDetailsManager gsEmployeeDetailsManager;
	
	public GSEmployeeDetailsManager getGsEmployeeDetailsManager() {
		return gsEmployeeDetailsManager;
	}

	public void setGsEmployeeDetailsManager(
			GSEmployeeDetailsManager gsEmployeeDetailsManager) {
		this.gsEmployeeDetailsManager = gsEmployeeDetailsManager;
	}

	public void setDataTransferManager(DataTransferManager dataTransferManager) {
		this.dataTransferManager = dataTransferManager;
	}
	
	public void setGsInfoManager(GsInfoManager gsInfoManager) {
		this.gsInfoManager = gsInfoManager;
	}
	
	public void setReviewCommentsDOM(ReviewCommentsDOM reviewCommentsDOM) {
		this.reviewCommentsDOM = reviewCommentsDOM;
	}
	
	public void setBuisnessValidationManager(
			BuisnessValidationManager buisnessValidationManager) {
		this.buisnessValidationManager = buisnessValidationManager;
	}

	public void setAppMetaDataDOM(AppMetaDataDOM appMetaDataDOM) {
		this.appMetaDataDOM = appMetaDataDOM;
	}
	
	private TaskAndNotificationsManager taskAndNotificationsManager;
	
	public void setTaskAndNotificationsManager(
			TaskAndNotificationsManager taskAndNotificationsManager) {
		this.taskAndNotificationsManager = taskAndNotificationsManager;
	}
	
	private UserDomainObjectManager userDomainObjectManager;
	
	public void setUserDomainObjectManager(
			UserDomainObjectManager userDomainObjectManager) {
		this.userDomainObjectManager = userDomainObjectManager;
	}
	
	private GenericVisaWF genericVisaWF;
	
	public void setGenericVisaWF(GenericVisaWF genericVisaWF) {
		this.genericVisaWF = genericVisaWF;
	}
	
	private FNPManager fnpManager;
	
	public void setFnpManager(FNPManager fnpManager) {
		this.fnpManager = fnpManager;
	}
	
	public ae.pcfc.cldos.online.common.etksdb.domain.manager.ClientDOM getClientDOM() {
		return clientDOM;
	}

	public void setClientDOM(
			ae.pcfc.cldos.online.common.etksdb.domain.manager.ClientDOM clientDOM) {
		this.clientDOM = clientDOM;
	}

	public ae.pcfc.cldos.online.common.tscdb.domain.manager.TTscClientCompanyDOM gettTscClientCompanyDOM() {
		return tTscClientCompanyDOM;
	}

	public void settTscClientCompanyDOM(
			ae.pcfc.cldos.online.common.tscdb.domain.manager.TTscClientCompanyDOM tTscClientCompanyDOM) {
		this.tTscClientCompanyDOM = tTscClientCompanyDOM;
	}

	
	/**
	 * @param clientId
	 * @return
	 */
	private String getCompanyLicNo(Long clientId){
		Client client = clientDOM.getClientById(clientId);
		TTscClientCompany tTscClientCompany = tTscClientCompanyDOM.getCompanyByTrakheesId(client.getCTrakheesId());
		return tTscClientCompany.getCcLicNo();
	}
	
	/**
	 * 
	 * Company admin decision handler method, generic for all processes
	 */
	@Transactional(rollbackFor=Exception.class)
	public AppSaveResponseVO companyAdminAction(AdminDecisionVO adminDecisionVO) throws Exception {
		AppSaveResponseVO appSaveResponseVO = new AppSaveResponseVO();
		String appId = adminDecisionVO.getApplicationId();
		
		User user = userDomainObjectManager.findUserByUserName(adminDecisionVO.getUserVO().getUsername());
		adminDecisionVO.getUserVO().setAdmin(true);
		
		String coLicNo = getCompanyLicNo(user.getClientId());
		
		AppMetaData appMetaData = appMetaDataDOM.getAppMetaDataById(appId);
		if(!user.getClientId().equals(appMetaData.getClientId())){
			throw new BadAppException("Bad app");
		}
		if(!AppMetaDataDOMImpl.STEPS_STATUSES_MAPPING.get(Steps.MAIN_ADMIN_APPROVE).contains(appMetaData.getStatusCode())){
			throw new BadAppException("Bad app");
		}
			
		taskAndNotificationsManager.completeAllByAppId(Long.parseLong(appId));
		
		/*Handle action for approve*/
		if(adminDecisionVO.getStrActionType().equals(AdminDecision.APPROVED.getAdminDecision())){
			/*LICENSE AND LEASE VALIDATION*/
		/*	if(!appMetaData.getProcessCode().equals(Process.PROCESS_CANCEL_VISIT_VISA) && 
					!appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION)){
				buisnessValidationManager.validateCompany(coLicNo);
				if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
					buisnessValidationManager.validateEmployeeQuota(coLicNo, user.getClientId());
				}
			}*/
			String clientRefNo = null;
			if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
				buisnessValidationManager.validateEmployee(appMetaData.getEmployeeDetail().getEdPsprtName(), 
						appMetaData.getEmployeeDetail().getPassportDetail().getPpPsprtNo(),false);
				buisnessValidationManager.validateOnlineEmpVisaData(coLicNo,appMetaData.getEmployeeDetail().getEdPsprtName(), appMetaData.getEmployeeDetail().getPassportDetail().getPpPsprtNo());
				if(appMetaData.getApplicationId().toString().equals(appMetaData.getClientRefNo())){
					clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_EMPLOYMENT_VISA);
					appMetaData.setClientRefNo(clientRefNo);
				}
			}else if (appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
				buisnessValidationManager.validateEmployee(appMetaData.getEmployeeDetail().getPassportDetail().getPpPsprtNameEng(), 
						appMetaData.getEmployeeDetail().getPassportDetail().getPpPsprtNo(),true);
				buisnessValidationManager.validateOnlineVisitVisaData(coLicNo);
				if(appMetaData.getApplicationId().toString().equals(appMetaData.getClientRefNo())){
					clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_VISIT_VISA);
					appMetaData.setClientRefNo(clientRefNo);
				}
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA_RENEWAL)){
					buisnessValidationManager.validateOnlineEmpVisaRenewalData(coLicNo,appMetaData.getEmploymentVisaRenew().getEvrEmployeeId());
					gsInfoManager.isRequestExist(Process.PROCESS_EMPLOYMENT_VISA_RENEWAL,appMetaData.getEmploymentVisaRenew().getEvrEmployeeId(), null);
					if(!gsEmployeeDetailsManager.validateEmployee(appMetaData.getEmploymentVisaRenew().getEvrEmployeeId(), 
							coLicNo)){
						throw new InvalidEmpIdException();
					}
					if(appMetaData.getApplicationId().toString().equals(appMetaData.getClientRefNo())){
						clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_EMPLOYMENT_VISA_RENEWAL);
						appMetaData.setClientRefNo(clientRefNo);
					}
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION)){
				buisnessValidationManager.validateOnlineEmpVisaTerminationData(coLicNo);
				gsInfoManager.isRequestExist(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION,appMetaData.getEmploymentVisaCancel().getEvcEmployeeId(), null);
				if(!gsEmployeeDetailsManager.validateEmployee(appMetaData.getEmploymentVisaCancel().getEvcEmployeeId(),
						coLicNo)){
					throw new InvalidEmpIdException();
				}
				if(appMetaData.getApplicationId().toString().equals(appMetaData.getClientRefNo())){
					clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION);
					appMetaData.setClientRefNo(clientRefNo);
				}
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_CANCEL_VISIT_VISA)){
				gsInfoManager.isRequestExist(Process.PROCESS_CANCEL_VISIT_VISA,null, appMetaData.getVisitVisaCancel().getVvcEmployeeId());
				if(!gsEmployeeDetailsManager.validateVisitor(appMetaData.getVisitVisaCancel().getVvcEmployeeId(), 
						coLicNo)){
					throw new InvalidEmpIdException();
				}
				if(appMetaData.getApplicationId().toString().equals(appMetaData.getClientRefNo())){
					clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_CANCEL_VISIT_VISA);
					appMetaData.setClientRefNo(clientRefNo);
				}
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_NOC_LETTERS)){
				buisnessValidationManager.validateOnlineNOCLettersData(coLicNo);
				if(!gsEmployeeDetailsManager.validateEmployee(appMetaData.getNocLetter().getNlEmployeeId(), 
						coLicNo)){
					throw new InvalidEmpIdException();
				}
				if(appMetaData.getApplicationId().toString().equals(appMetaData.getClientRefNo())){
					clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_NOC_LETTERS);
					appMetaData.setClientRefNo(clientRefNo);
				}
			}
			
			appMetaData.setStatusCode(ApplicationStatus.STATUS_APPROVED_BY_ONLINE_ADMIN);
			GSFinancialDataVO gsFinancialDataVO = null;
			String overLoadEmpCode = null; 
			if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA) || appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
				gsFinancialDataVO = gsInfoManager.retriveFinancialData(coLicNo, user.getClientId());
			}
			if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA) && (((gsFinancialDataVO.getRequiredAllowed()!=0) && (gsFinancialDataVO.getActualEmplyeesNum() >= gsFinancialDataVO.getAllowed()) && (gsFinancialDataVO.getActualEmplyeesNum() <= gsFinancialDataVO.getRequiredAllowed())))){
				overLoadEmpCode = ConstantsFNP.FNP_OVERLOAD_EMP_SERV_CODE;
			}
			//add param list here
			if(adminDecisionVO.getFnpServiceCode()!=null && !adminDecisionVO.getFnpServiceCode().isEmpty()){
				FNPPaymentAdviceVO fnpPaymentAdviceVO  = 
						fnpManager.generatePayment(appMetaData.getApplicationId(), user.getUUsername(), 
						adminDecisionVO.getFnpServiceCode(),adminDecisionVO.getFnpParams(),overLoadEmpCode,appMetaData.getClientRefNo());
				
				appMetaData.setPaymentAdviceNo(fnpPaymentAdviceVO.getPaymentAdviceNumber());
				appMetaData.getTempFileStorages().add(fnpPaymentAdviceVO.getStoredPaymentAdvice());
			}
			
			//BG check
			if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA) || appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
				Double bgBalance = gsFinancialDataVO.getBankGuaranteeBalance();
				try{
					FNPPaymentAdviceVO bgfnpPaymentAdviceVO = null;
					if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA) && 
							bgBalance.compareTo(ConstantsGS.__BG_EMP_VISA)<0){
						 bgfnpPaymentAdviceVO  = 
								fnpManager.generatePayment(appMetaData.getApplicationId(), user.getUUsername(), 
										ConstantsFNP.FNP_EMP_VISA_BG_SERVICE_CODE,null,null,appMetaData.getClientRefNo());
						gsInfoManager.addEmpVisaBG(coLicNo, user.getUUsername());
						appMetaData.setBgPaymentAdviceNo(bgfnpPaymentAdviceVO.getPaymentAdviceNumber());
						appMetaData.getTempFileStorages().add(bgfnpPaymentAdviceVO.getStoredPaymentAdvice());
					} else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA) && 
							bgBalance.compareTo(ConstantsGS.__BG_VISIT_VISA)<0){
						 bgfnpPaymentAdviceVO  = 
								fnpManager.generatePayment(appMetaData.getApplicationId(), user.getUUsername(), 
										ConstantsFNP.FNP_VISIT_VISA_BG_SERVICE_CODE_ARAB_NATIONAL,null,null,appMetaData.getClientRefNo());
						gsInfoManager.addVisitVisaBG(coLicNo, user.getUUsername());	
						appMetaData.setBgPaymentAdviceNo(bgfnpPaymentAdviceVO.getPaymentAdviceNumber());
						appMetaData.getTempFileStorages().add(bgfnpPaymentAdviceVO.getStoredPaymentAdvice());
					}
					
				}catch (Exception e) {
					e.printStackTrace();
					if(appMetaData.getPaymentAdviceNo()!=null){
						fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
								appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
					}
					if(appMetaData.getBgPaymentAdviceNo()!=null){
						fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
								appMetaData.getBgPaymentAdviceNo(),appMetaData.getClientRefNo());
						if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
							gsInfoManager.removeEmpVisaBG(coLicNo,  user.getUUsername());
						}else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
							gsInfoManager.removeVisitVisaBG(coLicNo,  user.getUUsername());
						}
					}
					throw e;
				}
			}
			
			
			/*handle action of reject*/
		} else if(adminDecisionVO.getStrActionType().equals(AdminDecision.REJECTED.getAdminDecision())){
			appMetaData.setStatusCode(ApplicationStatus.STATUS_REJECTED_BY_ONLINE_ADMIN);
			taskAndNotificationsManager.sendTask(appMetaData, TaskMaster.__ALL_RESUBMIT);
			/*handle action of cancel*/
		} else if(adminDecisionVO.getStrActionType().equals(AdminDecision.CANCELLED.getAdminDecision())){
			appMetaData.setStatusCode(ApplicationStatus.STATUS_CANCELED_BY_ONLINE_ADMIN);
		}
		
		//appMetaDataDOM.update(appMetaData);
		
		/*add action comment*/
		ReviewComments reviewComments = new ReviewComments();
		reviewComments.setApplicationId(appMetaData.getApplicationId());
		reviewComments.setStatusCode(appMetaData.getStatusCode());
		reviewComments.setRcUserName(user.getUUsername());
		reviewComments.setRcComments(adminDecisionVO.getComment());
		reviewCommentsDOM.add(reviewComments);
		
		/*send notification*/
		NotificationVO notificationVO = new NotificationVO();
		notificationVO.setOnlineAppId(appMetaData.getApplicationId().toString());
		Map<Object, Object> parameters = new HashMap<Object, Object>();
		parameters.put("comments", adminDecisionVO.getComment());
		notificationVO.setParameters(parameters);
		taskAndNotificationsManager.sendNotification(appMetaData, notificationVO);
		
		boolean wfFlag = true;
		if(appMetaData.getWfIncidentId() == null){
			wfFlag = false;
		}
		
		/*
		 * transfer request to GS
		 */
		if(adminDecisionVO.getStrActionType().equals(AdminDecision.APPROVED.getAdminDecision())){
			if(appMetaData.getWfIncidentId() == null){
				Integer incident;
				try{		
					incident = launchUltimusIncident(appMetaData,coLicNo);
				}catch (Exception e) {
					e.printStackTrace();
					if(appMetaData.getPaymentAdviceNo()!=null){
						fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
								appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
					}
					if(appMetaData.getBgPaymentAdviceNo()!=null){
						fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
								appMetaData.getBgPaymentAdviceNo(),appMetaData.getClientRefNo());
						if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
							gsInfoManager.removeEmpVisaBG(coLicNo,  user.getUUsername());
						}else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
							gsInfoManager.removeVisitVisaBG(coLicNo,  user.getUUsername());
						}
					}
					throw new UltimusAppException(e);
				}
				appMetaData.setWfIncidentId(incident.toString());
				appMetaData.setWfInitiatedBy(user.getUUsername());
			}
			
			TransferDataVO transferDataVO = new TransferDataVO();
			transferDataVO.setCompanyLicenseNo(coLicNo);
			transferDataVO.setAppMetaData(appMetaData);
			try{
				dataTransferManager.transferAppDateToOfflineSystem(transferDataVO);
			} catch(Exception  e){
				e.printStackTrace();
				fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(),
						appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
				if(appMetaData.getBgPaymentAdviceNo()!=null){
					fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
							appMetaData.getBgPaymentAdviceNo(),appMetaData.getClientRefNo());
					
					if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
						gsInfoManager.removeEmpVisaBG(coLicNo, user.getUUsername());
					} else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
						gsInfoManager.removeVisitVisaBG(coLicNo, user.getUUsername());
					}
				}
				throw new Exception(e);
			}
			
			NotificationVO notificationVO1 = new NotificationVO();
			notificationVO.setOnlineAppId(appMetaData.getApplicationId().toString());
			Map<Object, Object> parameters1 = new HashMap<Object, Object>();
			notificationVO1.setParameters(parameters1);
			taskAndNotificationsManager.sendNotification(appMetaData, notificationVO1);
			//transferDataToGS(appMetaData, adminDecisionVO.getUserVO(), coLicNo);
		}
		/*
		 * end of transfer
		 */
		
		//Call Ultimus 
		if(wfFlag){
			MainUserActionGVarVO mainUserActionGVarVO = new MainUserActionGVarVO();
			mainUserActionGVarVO.setG_ApplicationID(appMetaData.getApplicationId().toString());
			mainUserActionGVarVO.setG_MainUserDecision(adminDecisionVO.getStrActionType());
			
			CompleteStepVO completeStepVO = new CompleteStepVO();
			
			completeStepVO.setStrStepName(UltimusConstants.MAIN_USER_APPROVAL_STEP);
			completeStepVO.setStrUserName(ConstantsWF.ULTIMUS_ANONYMOUS_USER);
			completeStepVO.setnIncidentNumber(new Integer(appMetaData.getWfIncidentId()));
			
			try{
				genericVisaWF.completeStep(appMetaData.getProcessCode(), completeStepVO, mainUserActionGVarVO);
			} catch (Exception e) {
				e.printStackTrace();
				if(appMetaData.getPaymentAdviceNo()!=null){
					fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
							appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
				}
				try{
					gsInfoManager.cancelGSAppRequest(appMetaData.getClientRefNo());
					}catch (Exception e1) {}
				if(appMetaData.getBgPaymentAdviceNo()!=null){
					fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
							appMetaData.getBgPaymentAdviceNo(),appMetaData.getClientRefNo());
					if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
						gsInfoManager.removeEmpVisaBG(coLicNo, user.getUUsername());
					} else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)) {
						gsInfoManager.removeVisitVisaBG(coLicNo, user.getUUsername());
					}
				}
				throw new UltimusAppException(e);
			}
		}
		appMetaDataDOM.update(appMetaData);
		appSaveResponseVO.setReferenceNo(appMetaData.getClientRefNo());
		appSaveResponseVO.setIncidentNo(appMetaData.getWfIncidentId());
		if(appMetaData.getWfIncidentId() == null){
			appSaveResponseVO.setIncidentNo(ConstantsGS.WF_STATUS_EMPTY);
		}
	
		return appSaveResponseVO;
		
	}
	
	@Transactional
	public void cancelProcess(String appId, UserVO userVO) throws Exception{
		User user = userDomainObjectManager.findUserByUserName(userVO.getUsername());
		
		AppMetaData appMetaData = appMetaDataDOM.getPlainAppMetaDataById(appId);
		if(!user.getClientId().equals(appMetaData.getClientId())){
			throw new BadAppException("Bad app");
		}
		
		taskAndNotificationsManager.completeAllByAppId(Long.parseLong(appId));
		appMetaData.setStatusCode(ApplicationStatus.STATUS_CANCELED_ON_RESUBMITION);
		
		appMetaDataDOM.update(appMetaData);
		
		if(appMetaData.getWfIncidentId() != null){
			VisaResubmitGVarVO visaResubmitGVarVO = new VisaResubmitGVarVO();
			visaResubmitGVarVO.setG_ApplicationID(appMetaData.getApplicationId().toString());
			if(!userVO.isAdmin()){
				visaResubmitGVarVO.setG_ApplicationResubmittedBy(EmployeeType.EMPLOYEE.getEmployeeType());
			}else{
				visaResubmitGVarVO.setG_ApplicationResubmittedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
			}
			visaResubmitGVarVO.setG_ApplicationResubmitDecision(ApplicationResubmitDecision.CANCELLED.getResubmitDecision());
			
			CompleteStepVO completeStepVO = new CompleteStepVO();
			
			completeStepVO.setStrStepName(UltimusConstants.RESUBMIT_ONLINE_APPLICATION_STEP);
			completeStepVO.setStrUserName(ConstantsWF.ULTIMUS_ANONYMOUS_USER);
			completeStepVO.setnIncidentNumber(new Integer(appMetaData.getWfIncidentId()));
			
			genericVisaWF.completeStep(appMetaData.getProcessCode(), completeStepVO, visaResubmitGVarVO);
		}
		
	}
	
	/**
	 * @param appMetaData
	 * @param visaSubmitGVarVO
	 * @return
	 * @throws Exception
	 */
	private Integer launchUltimusIncident(AppMetaData appMetaData,String coLicNo) throws Exception{
		Integer incident = null;
		VisaSubmitGVarVO visaSubmitGVarVO = new VisaSubmitGVarVO();
			if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA) || appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
				visaSubmitGVarVO.setG_ApplicationID(appMetaData.getApplicationId().toString());
				visaSubmitGVarVO.setG_ApplicationSubmissionMedium(ConstantsCommon.APPLICATION_SUBMISSION_MEDIUM_ONLINE);
				if(appMetaData.getEmployeeDetail() != null){
					visaSubmitGVarVO.setG_EPSubmissionMethod(appMetaData.getEmployeeDetail().getEdEpCollMethd());
				}
				visaSubmitGVarVO.setG_ApplicationLaunchedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
			}
			if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
				EmploymentVisaAppInfoVO employmentVisaAppInfoVO = new EmploymentVisaAppInfoVO();
				getMapper().map(appMetaData.getEmployeeDetail(), employmentVisaAppInfoVO);
				getMapper().map(appMetaData.getEmployeeDetail().getAddressDetail(), employmentVisaAppInfoVO);
				getMapper().map(appMetaData.getEmployeeDetail().getPassportDetail(), employmentVisaAppInfoVO);
				getMapper().map(appMetaData.getEmployeeDetail().getPersonalDetail(), employmentVisaAppInfoVO);
				String edSrc = appMetaData.getEmployeeDetail().getEdSrc();
				if(ServiceMaster.SERVICE_CODE_EMP_OUTSIDE.toString().equals(edSrc)
						|| ServiceMaster.SERVICE_CODE_EMP_INSIDE.toString().equals(edSrc)){
					employmentVisaAppInfoVO.setG_Employee_Source(UltimusConstants.EMP_SOURCE_NEW);
				}else if(ServiceMaster.SERVICE_INTERNAL_TRANSFER.toString().equals(edSrc)){
					employmentVisaAppInfoVO.setG_Employee_Source(UltimusConstants.EMP_SOURCE_INTERNAL_TRANSFER);
				}else{
					employmentVisaAppInfoVO.setG_Employee_Source(UltimusConstants.EMP_SOURCE_TANSFER_SPONSOR);
				}
				incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(), new LaunchIncedentVO(), visaSubmitGVarVO, employmentVisaAppInfoVO);
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
				VisitVisaAppInfoVO visitVisaAppInfoVO = new VisitVisaAppInfoVO();
				getMapper().map(appMetaData.getEmployeeDetail(), visitVisaAppInfoVO);
				getMapper().map(appMetaData.getEmployeeDetail().getPassportDetail(), visitVisaAppInfoVO);
				getMapper().map(appMetaData.getVisitVisa(), visitVisaAppInfoVO);
				incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(), new LaunchIncedentVO(), visaSubmitGVarVO, visitVisaAppInfoVO);
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA_RENEWAL)){
				EmploymentVisaRenewAppInfo employmentVisaRenewAppInfo = new EmploymentVisaRenewAppInfo();
				getMapper().map(appMetaData.getEmploymentVisaRenew(), employmentVisaRenewAppInfo);
				employmentVisaRenewAppInfo.setG_Post_No(appMetaData.getClientRefNo());
				
				EVRenewalSubmGVarVO evRenewalSubmGVarVO = new EVRenewalSubmGVarVO();
				evRenewalSubmGVarVO.setG_ApplicationID(appMetaData.getApplicationId().toString());
				evRenewalSubmGVarVO.setG_ApplicationSubmissionMedium(ConstantsCommon.APPLICATION_SUBMISSION_MEDIUM_ONLINE);
				evRenewalSubmGVarVO.setG_ApplicationLaunchedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
				evRenewalSubmGVarVO.setG_MedAppLetterSubMethod(appMetaData.getEmploymentVisaRenew().getEvrMedLetterSubmission());
				incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(), new LaunchIncedentVO(), evRenewalSubmGVarVO, employmentVisaRenewAppInfo);
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION)){
				EmploymentVisaCancelationAppInfoVO employmentVisaCancelationAppInfoVO = new EmploymentVisaCancelationAppInfoVO();
				getMapper().map(appMetaData.getEmploymentVisaCancel(), employmentVisaCancelationAppInfoVO);
				employmentVisaCancelationAppInfoVO.setG_ApplicationDate(appMetaData.getApplicationDate());
				
				TerminateEVSubmGVarVO terminateEVSubmGVarVO = new TerminateEVSubmGVarVO();
				terminateEVSubmGVarVO.setG_ApplicationID(appMetaData.getApplicationId().toString());
				terminateEVSubmGVarVO.setG_ApplicationSubmissionMedium(ConstantsCommon.APPLICATION_SUBMISSION_MEDIUM_ONLINE);
				terminateEVSubmGVarVO.setG_EmployeeType(UltimusConstants.EMPLOYEE_TYPE_RP);
				terminateEVSubmGVarVO.setG_ApplicationLaunchedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
				terminateEVSubmGVarVO.setG_RPCancellationMethod(appMetaData.getEmploymentVisaCancel().getEvcCancelform());
				incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(),  new LaunchIncedentVO(), terminateEVSubmGVarVO, employmentVisaCancelationAppInfoVO);
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_CANCEL_VISIT_VISA)){
				VisitVisaCancelAppInfo visitVisaCancelAppInfo = new VisitVisaCancelAppInfo();
				getMapper().map(appMetaData.getVisitVisaCancel(), visitVisaCancelAppInfo);
				visitVisaCancelAppInfo.setG_ApplicationDate(appMetaData.getApplicationDate());
				
				BaseSubmitGVariablesVO baseSubmitGVariablesVO = new BaseSubmitGVariablesVO();
				baseSubmitGVariablesVO.setG_ApplicationID(appMetaData.getApplicationId().toString());
				baseSubmitGVariablesVO.setG_ApplicationSubmissionMedium(ConstantsCommon.APPLICATION_SUBMISSION_MEDIUM_ONLINE);
				baseSubmitGVariablesVO.setG_ApplicationLaunchedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
				incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(), new LaunchIncedentVO(), baseSubmitGVariablesVO, visitVisaCancelAppInfo);
			}else if(appMetaData.getProcessCode().equals(Process.PROCESS_NOC_LETTERS)){
				NocLetterAppInfoVO nocLetterAppInfoVO = new NocLetterAppInfoVO();
				getMapper().map(appMetaData.getNocLetter(), nocLetterAppInfoVO);
				
				//call nst ws to get the missing NOC details
				NOCDetailsFromGSVO nocDetailsFromGSVO = gsEmployeeDetailsManager.getNOCDetailsById(appMetaData.getNocLetter().getNlEmployeeId(),coLicNo,appMetaData.getApplicationId().toString());
				getMapper().map(nocDetailsFromGSVO, nocLetterAppInfoVO);
				nocLetterAppInfoVO.setG_PaymentApproved("TRUE");
				nocLetterAppInfoVO.setG_IfLetterSelected(buisnessValidationManager.getNOCLetterCode(appMetaData.getNocLetter().getNlNocLetterType(), appMetaData.getNocLetter().getNlTextFormat()));
				
				BaseSubmitGVariablesVO baseSubmitGVariablesVO = new BaseSubmitGVariablesVO();
				baseSubmitGVariablesVO.setG_ApplicationID(appMetaData.getApplicationId().toString());
				baseSubmitGVariablesVO.setG_ApplicationSubmissionMedium(ConstantsCommon.APPLICATION_SUBMISSION_MEDIUM_ONLINE);
				baseSubmitGVariablesVO.setG_ApplicationLaunchedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
				incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(), new LaunchIncedentVO(), baseSubmitGVariablesVO, nocLetterAppInfoVO);
			}
		return incident;	
	}
}
